package com.bonjour.common.view;

import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;

import com.bonjour.common.core.IRequest;
import com.bonjour.common.core.RpcReply;
import com.bonjour.common.helper.CollectsHelper;
import com.bonjour.common.helper.JsonHelper;
import com.bonjour.common.helper.ThreadFactoryHelper;
import com.bonjour.common.support.IConstant;
import com.bonjour.common.support.OperationLog;
import com.bonjour.common.view.parser.ApiOperation;
import com.bonjour.common.view.parser.RequestContext;
import com.bonjour.common.view.parser.RequestSession;

@Aspect
@Order(0)
@Deprecated
public final class ApiOperationInterceptor {
	private static final Logger OUT = LoggerFactory.getLogger(OperationLog.class);
	private static final ExecutorService LOG_EXECUTOR = Executors.newSingleThreadExecutor(ThreadFactoryHelper.threadFactoryOf("operation-log"));
	private final ApplicationContext context;

	ApiOperationInterceptor(ApplicationContext context) {
		this.context = context;
	}

	@Around("@annotation(operation)")
	public Object around(ProceedingJoinPoint joinPoint, ApiOperation operation) throws Throwable {
		Object response;
		Object[] args = joinPoint.getArgs();
		try {
			verifyArgs(args);
			response = joinPoint.proceed(joinPoint.getArgs());
			operationLog(joinPoint, operation, response);
		} catch (Throwable e) {
			operationLog(joinPoint, operation, e);
			throw e;
		}
		return response;
	}

	/** 校验参数 **/
	private void verifyArgs(Object[] args) {
		if(!CollectsHelper.isNullOrEmpty(args)) {
			for(Object arg: args)
				if (arg instanceof IRequest) {
					((IRequest) arg).verify();
				}
		}
	}

	/** 记录操作日志 **/
	private void operationLog(final ProceedingJoinPoint joinPoint, final ApiOperation operation, final Object reply) {
		if(!"true".equalsIgnoreCase(context.getEnvironment().getProperty(IConstant.KEY_OPERATIONS_LOG_ENABLE))) {
			return;
		}
		if(!operation.note()) {
			return;
		}
		final Method method = joinPointMethod(joinPoint);
		if(method.getReturnType().equals(Void.TYPE)) {
			return;
		}
		final RequestSession session = RequestContext.get().getSession();
		if (null == session) {
			return;
		}
		session.operate = operation.name();
		//异步处理操作日志
		LOG_EXECUTOR.submit(() -> {
			OperationLog log = OperationLog.newborn(session, null);
			if(reply instanceof RpcReply) {
				log.setResponseBody(reply);
			} else if(reply instanceof Throwable) {
				log.setResponseBody(((Throwable)reply).getMessage());
			} else {
				log.setResponseBody(reply);
			}
			OUT.info("{}", JsonHelper.toJSONString(log));
		});
	}

	//获取拦截方法
	private Method joinPointMethod(ProceedingJoinPoint joinPoint) {
		return ((MethodSignature)joinPoint.getSignature()).getMethod();
	}
}
